package com.ronz.queue;

import java.util.Scanner;

/**
 * @Description 使用数组演示队列
 *              注意事项：
 *              - 在这里 front 为指向队列中第一个元素的指针
 *              - rear 为指向队列中最后一个元素的后一个位置的指针
 * @Author Ronz
 * @Date 2020/12/21 11:52
 * @Version 1.0
 */
public class No2_CircleArrayQueue {

    public static void main(String[] args) {
        CircleArrayQueue circleArrayQueue = new CircleArrayQueue(5);

        Scanner input = new Scanner(System.in);
        boolean flag = true;
        while(flag){
            No1_ArrayQueue.showMenu();
            String line = input.nextLine();
            char key = line.charAt(0);          // 获取输入的第一个关键字
            switch (key){
                case 's':       // 显示队列
                    circleArrayQueue.showQueue();
                    break;
                case 'a':       // 入队列
                    System.out.print("请输入要入队列的数：");
                    String num = input.nextLine();
                    circleArrayQueue.addQueue(Integer.valueOf(num));
                    break;
                case 'q':       // 出队列
                    try{
                        int queue = circleArrayQueue.quitQueue();
                        System.out.println(queue + " ---------- 出队列了！");
                    }catch (RuntimeException e){
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':       // 退出程序
                    flag = false;
                    input.close();
                    System.out.println("退出程序！");
                    break;
            }

        }
    }



}

/**
 * @Description 使用数组模拟环形队列
 * @Param
 * @return
 */
class CircleArrayQueue{
    private int maxSize;
    private int front;
    private int rear;
    private int[] arr;

    public CircleArrayQueue(int maxSize){
        this.maxSize = maxSize;
        front = rear = 0;
        arr = new int[maxSize];
    }

    /**
     * @Description 判断队列是否为空
     *              - 当 front == rear 时，队列为空
     * @Param []
     * @return boolean
     */
    public boolean isEmpty(){
        return front == rear;
    }

    /**
     * @Description 判断队列是否为满
     *              - 当 (rear + 1)%maxSize = front 时，队列为满
     * @Param []
     * @return boolean
     */
    public boolean isFull(){
        return (rear + 1) % maxSize == front;
    }

    /**
     * @Description 数据入队列
     * @Param [item]
     * @return void
     */
    public void addQueue(int item){
        // 1. 首先判断队列是否为满
        if (isFull()){
            System.out.println("队列已满，无法插入数据！");
        }else{
            // 2. 插入数据到队列中
            arr[rear] = item;
            // 3. rear 后移一位，因为 rear 有可能越界，所以需要取余才能形成环形队列
            rear =  (rear + 1) % maxSize;
            System.out.println(item + " +++++++++++ 入队列了！");
        }
    }

    /**
     * @Description 数据出队列，也就是队头数据出列
     * @Param []
     * @return int
     */
    public int quitQueue(){
        // 1. 首先判断队列是否为空
        if (isEmpty()){
            throw new RuntimeException("队列为空，无法出队列！");
        }else{
            // 2. 数据出队列
            int temp = arr[front];
            // 3. front 后移一位，因为 front 有可能越界，所以需要取余
            front = (front + 1) % maxSize;
            return temp;
        }
    }

    /**
     * @Description 打印队列数据
     * @Param []
     * @return void
     */
    public void showQueue(){
        // 1. 首先判断队列是否为空
        if (isEmpty()){
            System.out.println("队列为空！");
        } else {
            // 2. 不为空则打印数据
            for (int i=front; i<(getSize() + front); i++){
                System.out.println("a[" + i % maxSize + "] = " + arr[i % maxSize]);
            }
        }

    }

    /**
     * @Description 获取队列长度（元素个数）
     * @Param []
     * @return int
     */
    public int getSize(){
        return (rear - front + maxSize) % maxSize;
    }

}
